package com.atguigu.tingshu.user.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.user.UserListenProcess;
import com.atguigu.tingshu.user.service.UserListenProcessService;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.atguigu.tingshu.vo.user.LastUserListenPlayVo;
import com.atguigu.tingshu.vo.user.UserListenProcessVo;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author Petrichor
 */
@Service
@Slf4j
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserListenProcessServiceImpl implements UserListenProcessService {


	private final MongoTemplate mongoTemplate;

	private final KafkaService kafkaService ;


	private final RedisTemplate<String , String> redisTemplate ;
	@Autowired
	public UserListenProcessServiceImpl(MongoTemplate mongoTemplate, KafkaService kafkaService, RedisTemplate<String, String> redisTemplate) {
		this.mongoTemplate = mongoTemplate;
		this.kafkaService = kafkaService;
		this.redisTemplate = redisTemplate;
	}
	/**
	 * @description: 获取声音播放进度
	 * @author Petrichor
	 * @date 2024/1/1 16:59
	 * @param trackId 声音id
	 * @return 该声音id 运行的秒伤
	 **/
	@Override
	public BigDecimal getTrackBreakSecond(Long userId, Long trackId) {
		//	根据用户Id,声音Id获取播放进度对象
		Query query = Query.query(Criteria.where("userId").is(userId).and("trackId").is(trackId));
		String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId) ;
		UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);

		//	判断
		if (null != userListenProcess){
			//	获取到播放的跳出时间
			return userListenProcess.getBreakSecond();
		}

		return new BigDecimal("0");
	}

	/**
	 * @description: 更新播放进度
	 * @author Petrichor
	 * @date 2024/1/1 15:59
	 * @param userId 当前登录用户id
	 * @param userListenProcessVo 专辑id 声音id 音频播放位置
	 **/
	@Override
	public void updateListenProcess(Long userId, UserListenProcessVo userListenProcessVo) {


		// TODO: 1.根据用户的id和声音的id从mongodb中进行数据查询
		Criteria criteria = Criteria
				.where("userId").is(userId)
				.and("trackId").is(userListenProcessVo.getTrackId())
				.and("albumId").is(userListenProcessVo.getAlbumId());
		Query query = new Query(criteria);
		// 调用工具类中的方法 使用户按照id 分别放到不同的表中 方便查询
		String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);
		UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class , collectionName);

		// TODO: 2.如果查询不到数据，构建数据，将数据存储到mongodb中
		if(userListenProcess == null) {

			userListenProcess = new UserListenProcess() ;
			userListenProcess.setUserId(userId);
			userListenProcess.setId(ObjectId.get().toHexString());
			userListenProcess.setTrackId(userListenProcessVo.getTrackId());
			userListenProcess.setAlbumId(userListenProcessVo.getAlbumId());
			userListenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
			userListenProcess.setCreateTime(new Date());
			userListenProcess.setUpdateTime(new Date());
			// 保存数据到mongodb中
			mongoTemplate.save(userListenProcess , collectionName) ;

			log.info("保存新的声音播放进度数据到mongodb中...");

		}else {
			// TODO: 3.如果可以查询到数据，最数据进行更新操作
			Update update = new Update() ;
			update.set("breakSecond" , userListenProcessVo.getBreakSecond()) ;
			update.set("updateTime" , new Date()) ;
			mongoTemplate.updateFirst(query , update , collectionName) ;
			log.info("修改了声音播放进度...");
		}

		// TODO: 4.更新声音播放量
		// trackId + 日期 + userId
		String redisKey = "track:play:" + userListenProcessVo.getTrackId() + ":" + DateUtil.format(new Date() , "yyyyMMdd") + ":" + userId ;
		Boolean hasKey = redisTemplate.hasKey(redisKey);
		//通过key 判断 当天是否播放过 不存在 则没有播放过 更新播放数据
		if(!hasKey) {
			// 记录播放量

			// 创建TrackStatMqVo对象，封装要发送的消息
			TrackStatMqVo trackStatMqVo = new TrackStatMqVo() ;
			trackStatMqVo.setBusinessNo(UUID.randomUUID().toString().replace("-" , ""));
			trackStatMqVo.setAlbumId(userListenProcessVo.getAlbumId());
			trackStatMqVo.setTrackId(userListenProcessVo.getTrackId());
			// 播放量
			trackStatMqVo.setStatType(SystemConstant.TRACK_STAT_PLAY);
			trackStatMqVo.setCount(1);

			//  发送消息
			kafkaService.sendMsg(KafkaConstant.QUEUE_TRACK_STAT_UPDATE , JSON.toJSONString(trackStatMqVo));

			// 存储redisKey到redis中
			redisTemplate.opsForValue().set(redisKey , "1" , 1 , TimeUnit.DAYS);

		}
	}
	/**
	 * @description: 获取最近一次播放声音
	 * @author Petrichor
	 * @date 2024/1/2 20:14
	 * @return LastUserListenPlayVo 专辑id 声音id
	 **/
	@Override
	public LastUserListenPlayVo getLatelyTrack(Long userId) {

		// 构建搜索条件对象
		Query query = new Query()
				.limit(1)
				.with(Sort.by(Sort.Direction.DESC , "updateTime"));

		// 查询数据
		String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId) ;
		UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);

		// 结果数据封装
		LastUserListenPlayVo lastUserListenPlayVo = new LastUserListenPlayVo() ;
		lastUserListenPlayVo.setAlbumId(userListenProcess.getAlbumId());
		lastUserListenPlayVo.setTrackId(userListenProcess.getTrackId());

		// 返回结果数据
		return lastUserListenPlayVo;
	}
}
